using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using BriansClimb.DrawableGameObjects.GameScenes;
using BriansClimb.DrawableGameObjects.Buttons;
using BriansClimb.GameObjects;
using BriansClimb;

namespace BriansClimb
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        protected readonly GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;
        private GameTime previousGameTime;

        private AudioManager audioManager;

        //Game Scene Background Textures
        protected Texture2D menuBackgroundTexture;
        protected Texture2D wallBackgroundTexture;

        //Game Scene Button Textures
        protected Texture2D saveButtonTexture;
        protected Texture2D loadButtonTexture;
        protected Texture2D backButtonTexture;

        //Text Menu Fonts
        protected SpriteFont normalFont, selectedFont;

        //Game Scenes
        protected StartScene startScene;
        protected WallCustomizeScene wallCustomizeScene;
        protected WallSelectionScene wallSelectionScene;
        protected PlayerCustomizeScene playerCustomizeScene;
        protected PlayerClimbScene playerClimbScene;
        protected VictoryScene victoryScene;
        protected FailureScene failureScene;

        protected SceneManager sceneManager;
        protected ButtonManager buttonManager;
        protected TextMenuComponent escTextMenuComponent;
        protected TextMenuComponent loadTextMenuComponent;
        protected FileManager fileManager;
        protected FileStatManager fileStatManager;

        //physics simulator
        protected FarseerGames.FarseerPhysics.PhysicsSimulator physicsSimulator;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);

            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            //Setting the screen resolution to 1280x1024 in full screen mode.
            this.graphics.PreferredBackBufferWidth = 1280;
            this.graphics.PreferredBackBufferHeight = 1024;
            //this.graphics.ToggleFullScreen();
            this.graphics.ApplyChanges();

            audioManager = new AudioManager(this);
            Components.Add(audioManager);
            Services.AddService(typeof(AudioManager), audioManager);

            //Enabling the mouse to be seen in the game window.
            this.IsMouseVisible = true;

            base.Initialize();


        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            physicsSimulator = new FarseerGames.FarseerPhysics.PhysicsSimulator(new FarseerGames.FarseerPhysics.Mathematics.Vector2(0, 0));
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
            Services.AddService(typeof(SpriteBatch), spriteBatch);

            //Loading the 2 different background textures for the game scenes.
            menuBackgroundTexture = Content.Load<Texture2D>(".\\Textures\\WallBackground");
            wallBackgroundTexture = Content.Load<Texture2D>(".\\Textures\\BackGround");
            //wallBackgroundTexture = Content.Load<Texture2D>(".\\Textures\\WallBackground");

            //Loading the text menu fonts for normal and selected states.
            normalFont = Content.Load<SpriteFont>(".\\Fonts\\MenuNormal");
            selectedFont = Content.Load<SpriteFont>(".\\Fonts\\MenuSelected");

            //creating the game file manager
            fileManager = new FileManager(this,physicsSimulator);
            fileStatManager = new FileStatManager(this);
            //pseudo-master physics engine
              
            //creating the game text menus
            escTextMenuComponent = new TextMenuComponent(this, normalFont, selectedFont);
            loadTextMenuComponent = new TextMenuComponent(this, normalFont, selectedFont);

            //creating the game start scene.
            startScene = new StartScene(this, menuBackgroundTexture, normalFont, selectedFont);

            //creating the game wall customization scene
            wallCustomizeScene = new WallCustomizeScene(this, escTextMenuComponent ,fileManager, fileStatManager,
                        wallBackgroundTexture, normalFont, selectedFont, physicsSimulator);

            //creating the game wall selection scene
            wallSelectionScene = new WallSelectionScene(this, fileManager, fileStatManager, menuBackgroundTexture,  
                        normalFont, selectedFont);

            //creating the game player customize scene
            playerCustomizeScene = new PlayerCustomizeScene(this, fileManager, fileStatManager, menuBackgroundTexture,
                        normalFont, selectedFont);

            //creating the game climbing wall scene
            playerClimbScene = new PlayerClimbScene(this, wallBackgroundTexture, loadTextMenuComponent, fileStatManager, 
                        physicsSimulator);

            //creating the game Victory Scene
            victoryScene = new VictoryScene(this, wallBackgroundTexture);

            //creating the game Fail Scene
            failureScene = new FailureScene(this, wallBackgroundTexture);

            //creating the game scene manager
            sceneManager = new SceneManager(this, startScene, wallCustomizeScene, wallSelectionScene, 
                        playerCustomizeScene, playerClimbScene, victoryScene, failureScene, fileManager, 
                        fileStatManager, escTextMenuComponent, loadTextMenuComponent, physicsSimulator);

            //creating the button manager
            buttonManager = new ButtonManager(this, sceneManager, wallCustomizeScene);


            //adding objects to component list. (order is important!!)
            Components.Add(startScene);
            Components.Add(wallSelectionScene);
            Components.Add(playerCustomizeScene);
            Components.Add(wallCustomizeScene);
            Components.Add(playerClimbScene);
            Components.Add(victoryScene);
            Components.Add(failureScene);
            Components.Add(loadTextMenuComponent);
            Components.Add(escTextMenuComponent);
            Components.Add(sceneManager);
            Components.Add(buttonManager);
            Components.Add(fileStatManager);

            //setting the start scene as the initial scene
            startScene.Show();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();
            base.Draw(gameTime);
            spriteBatch.End();
        }

        public FarseerGames.FarseerPhysics.PhysicsSimulator PhysicsSimulator
        {
            get { return physicsSimulator; }
            set { physicsSimulator = value; }
        }
    }
}
